package com.shuma.shopmanage.shopmodule.service.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuma.shopmanage.common.constant.RoleConstant;
import com.shuma.shopmanage.common.exception.ShopManageException;
import com.shuma.shopmanage.common.model.LoginUser;
import com.shuma.shopmanage.common.result.ResultCodeEnum;
import com.shuma.shopmanage.common.utils.RedisConstants;
import com.shuma.shopmanage.common.utils.RedisWorker;
import com.shuma.shopmanage.model.shop.dto.*;
import com.shuma.shopmanage.model.shop.model.GoodsProxy;
import com.shuma.shopmanage.model.shop.vo.PreviewVo;
import com.shuma.shopmanage.shopmodule.mapper.GoodsProxyMapper;
import com.shuma.shopmanage.shopmodule.service.GoodsProxyService;
import com.shuma.shopmanage.draftmodule.service.GoodsDraftService;
import com.shuma.shopmanage.draftmodule.service.NonDeliverableCityDraftService;
import com.shuma.shopmanage.draftmodule.service.StoragecitiesDraftService;
import com.shuma.shopmanage.model.draft.model.GoodsDraft;
import com.shuma.shopmanage.model.shop.constant.ShopConstant;
import com.shuma.shopmanage.model.shop.model.Goods;
import com.shuma.shopmanage.model.shop.model.NonDeliverableCity;
import com.shuma.shopmanage.model.shop.model.Storagecities;
import com.shuma.shopmanage.model.shop.vo.GoodsVo;
import com.shuma.shopmanage.model.shop.vo.PageVo;
import com.shuma.shopmanage.security.SecurityContextHolder;
import com.shuma.shopmanage.shopmodule.mapper.GoodsMapper;
import com.shuma.shopmanage.shopmodule.service.*;
import com.shuma.shopmanage.shopmodule.userFeign.UserFeignService;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {

    @Autowired
    private NonDeliverableCityService nonDeliverableCityService;

    @Autowired
    private StoragecitiesService storagecitiesService;

    @Resource
    private GoodsProxyService goodsProxyService;

    @Autowired
    private UserFeignService userFeignService;

    @Autowired
    private OperationService operationService;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsDraftService goodsDraftService;

    @Autowired
    private NonDeliverableCityDraftService nonDeliverableCityDraftService;

    @Autowired
    StoragecitiesDraftService storagecitiesDraftService;

    private List<NonDeliverableCity> nonDeliverableCityList;

    private Long id;

    private List<Storagecities> storagecitiesList;

    @Autowired
    private RedisWorker redisWorker;

    @Transactional
    public GoodsVo insertGood(GoodsDto goodsDto) {
        Goods goods;
        //商品上线不能修改
        //商品审批进行时不能修改
        if ((goodsDto.getStatus() != null && goodsDto.getStatus() == 1) || (goodsDto.getApprovalStatus() != null && goodsDto.getApprovalStatus() == 1)) {
            throw new ShopManageException("商品此时无法编辑", ResultCodeEnum.FAIL.getCode());
        }
        //参数校验
        parameterCheck(goodsDto);
        LoginUser loginUser = SecurityContextHolder.getLoginUser();
        try {
            //第一次添加
            if (goodsDto.getId() == null) {
                //生成唯一id
                id = redisWorker.nextId(RedisConstants.SHOP_GOODSID_KEY);
                goodsDto.setId(id);
                goodsDto.setCreateUserId(loginUser.getId());
                goodsDto.setManageUserId(loginUser.getId());
            }
            //修改商品
            else {
                if(goodsDto.getManageUserId() != loginUser.getId()){
                    throw new ShopManageException("不能操作此商品,",ResultCodeEnum.FAIL.getCode());
                }
                nonDeliverableCityService.removeByGoodsId(goodsDto.getId());
                storagecitiesService.removeByGoodsId(goodsDto.getId());
                //修改商品状态为未审核
                goodsDto.setApprovalStatus(0);
            }
            goods = BeanUtil.copyProperties(goodsDto, Goods.class);
            saveOrUpdate(goods);
            List<String> nonDeliverPostalCodeList = goodsDto.getNoDeliverPostalCodes();
            List<String> storagePostalCodeList = goodsDto.getStoragePostalCodes();
            //添加不能运送的城市
            SaveNonDeliverableCityList(goods, nonDeliverPostalCodeList);
            //添加库存城市
            saveStorageList(goods, storagePostalCodeList);
            //判断有无草稿
            Long goodsDraftId = goodsDto.getGoodsDraftId();
            if (goodsDraftId != null) {
                //删除商品对应的草稿
                goodsDraftService.removeById(goodsDraftId);
                nonDeliverableCityDraftService.removeByGoodsDraftId(goodsDraftId);
                storagecitiesDraftService.removeByGoodsDraftId(goodsDraftId);
            }
            //根据是否生成id判断
            String message = "";
            if (id == null)
                message = "编辑商品";
            else
                message = "新增商品";
            //生成操作表
            operationService.createOperation(goods, message);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ShopManageException("数据有误,插入失败", 204);
        }
        GoodsVo goodsVo = BeanUtil.copyProperties(goods, GoodsVo.class);
        return goodsVo;
    }


    /**
     * 根据用户ID查询商品
     * @param goodsPageDto 分页参数
     * @param userId 用户ID
     */
    @Override
    public PageVo queryPageByUid(GoodsPageDto goodsPageDto, Long userId) {
        Page<Goods> pageParam = new Page<>();
        BeanUtils.copyProperties(goodsPageDto, pageParam);
        QueryChainWrapper<Goods> wrapper = query()
                .and(true, qw -> wrapperByUid(qw, userId));
        //分页条件商品状态筛选
        if (!ObjectUtils.isEmpty(goodsPageDto.getStatus())) {
            wrapper.eq("status", goodsPageDto.getStatus());
        }

        //分页查询
        Page<Goods> pageResult = wrapper.page(pageParam);
        //分页数据转换 转vo
        PageVo<GoodsVo> goodsVoPageVo = page(pageResult);

        return goodsVoPageVo;
    }


    @Override
    public PageVo queryPage(GoodsPageDto goodsPageDto) {
        Page<Goods> pageParam = new Page<>();
        BeanUtils.copyProperties(goodsPageDto, pageParam);

        QueryChainWrapper<Goods> wrapper = query();
        //分页条件商品状态筛选
        if (!ObjectUtils.isEmpty(goodsPageDto.getStatus())) {
            wrapper.eq("status", goodsPageDto.getStatus());
        }
        //分页查询
        Page<Goods> pageResult = wrapper.page(pageParam);
        //分页数据转换 转vo
        PageVo<GoodsVo> goodsVoPageVo = page(pageResult);
        return goodsVoPageVo;
    }

    /**
     * 条件查询
     * @param queryDto 查询参数
     * @param goodsPageDto 分页参数
     */
    @Override
    public PageVo queryPageCondition(QueryDto queryDto, GoodsPageDto goodsPageDto) {
        Page<Goods> pageParam = new Page<>();
        BeanUtils.copyProperties(goodsPageDto, pageParam);

        QueryChainWrapper<Goods> wrapper = query();
        //分页条件商品状态筛选
        if (!ObjectUtils.isEmpty(goodsPageDto.getStatus())) {
            wrapper.eq("status", goodsPageDto.getStatus());
        }

        //筛选条件
        wrapper.and(qw -> queryCondition(qw, queryDto));

        //分页查询
        Page<Goods> pageResult = wrapper.page(pageParam);
        //分页数据转换 转vo
        PageVo<GoodsVo> goodsVoPageVo = page(pageResult);

        return goodsVoPageVo;
    }

    /**
     * 根据用户ID条件查询
     * @param queryDto 查询参数
     * @param goodsPageDto 分页参数
     * @param userId 用户ID
     */
    @Override
    public PageVo queryPageConditionByUid(QueryDto queryDto, GoodsPageDto goodsPageDto, Long userId) {
        Page<Goods> pageParam = new Page<>();
        BeanUtils.copyProperties(goodsPageDto, pageParam);

        List<Long> goodsIds = goodsProxyService.selectGoodsIdsByUid(userId);
        QueryChainWrapper<Goods> wrapper = query();
        //根据用户查wrapper 筛选登录用户是管理人或代理人的商品
        wrapper.and(qw -> wrapperByUid(qw, userId));
        //分页条件商品状态筛选
        if (!ObjectUtils.isEmpty(goodsPageDto.getStatus())) {
            wrapper.eq("status", goodsPageDto.getStatus());
        }
        //筛选条件
        wrapper.and(qw -> queryCondition(qw, queryDto));
        //筛选分页条件

        Page<Goods> pageResult = wrapper.page(pageParam);
        PageVo<GoodsVo> goodsVoPageVo = page(pageResult);
        return goodsVoPageVo;
    }

    /**
     * 根据用户查询wrapper
     * 筛选登录用户是管理人或代理人的商品
     * @param userId 用户id
     */
    private void wrapperByUid(QueryWrapper<Goods> wrapper, Long userId) {
        List<Long> goodsIds = goodsProxyService.selectGoodsIdsByUid(userId);
        wrapper
                //筛选登录用户是管理人的商品
                .eq("manageUserId", userId);
        if (!ObjectUtils.isEmpty(goodsIds)) {
            //筛选登录用户是代理人的商品
            wrapper.or().in("id", goodsIds);
        }
    }

    /**
     * 条件查询通用wrapper
     * @param queryDto 条件参数
     */
    private void queryCondition(QueryWrapper<Goods> wrapper, QueryDto queryDto) {
        wrapper.apply("true");
        if (!ObjectUtils.isEmpty(queryDto.getId())) {
            wrapper.eq("id", queryDto.getId());
        }

        if (!ObjectUtils.isEmpty(queryDto.getName())) {
            wrapper.like("name", "%" + queryDto.getName() + "%");
        }

        if (!ObjectUtils.isEmpty(queryDto.getOnTime())) {
            wrapper.eq("onTime", queryDto.getOnTime());
        }

        if (!ObjectUtils.isEmpty(queryDto.getDownTime())) {
            wrapper.eq("downTime", queryDto.getDownTime());
        }

        if (!ObjectUtils.isEmpty(queryDto.getStatus())) {
            wrapper.eq("status", queryDto.getStatus());
        }

        if (!ObjectUtils.isEmpty(queryDto.getManageUserName())) {
            List<Long> ids = userFeignService.
                    selectIdByLikeName(queryDto.getManageUserName());
            wrapper.in("manageUserId", ids);
        }
    }

    /**
     * 分页通用转换
     * 将Goods分页数据转GoodsVo数据
     */
    private PageVo<GoodsVo> page(Page<Goods> page) {
        List<Goods> records = page.getRecords();
        List<GoodsVo> goodsVos = records.stream().map(goods -> {
            GoodsVo goodsVo = new GoodsVo();
            BeanUtils.copyProperties(goods, goodsVo);

            //查询管理人名称和是否审批
            String name = userFeignService.selectNameById(goods.getManageUserId());
            Boolean isApproval = ShopConstant.APPROVAL_FINISH.equals(goods.getApprovalStatus());
            //设置管理人名称和是否审批
            goodsVo.setManageUserName(name);
            goodsVo.setIsApproval(isApproval);

            return goodsVo;
        }).collect(Collectors.toList());
        PageVo<GoodsVo> goodsVoPageVo = new PageVo<>();
        BeanUtils.copyProperties(page, goodsVoPageVo);
        goodsVoPageVo.setPages(page.getPages());
        goodsVoPageVo.setData(goodsVos);

        return goodsVoPageVo;
    }


    //商品批量下线
    @Override
    @Transactional
    public void goodsBathesOffline(ApproveDto approveDto) {
        for (Long id : approveDto.getIds()) {
            goodsOffline(id);
        }
    }

    @Override
    public boolean goodsOffline(Long id) {
        Goods goods = getById(id);
        if (goods == null) {
            throw new ShopManageException("无此商品", ResultCodeEnum.FAIL.getCode());
        }
        LoginUser loginUser = SecurityContextHolder.getLoginUser();
        if (!Objects.equals(goods.getManageUserId(), loginUser.getId()) && !Objects.equals(loginUser.getRole(), RoleConstant.ADMIN)) {
            throw new ShopManageException("商品" + id + ":" + "无权限发起下线", ResultCodeEnum.FAIL.getCode());
        }
        if (goods.getStatus() == 0) {
            throw new ShopManageException("商品" + id + ":" + "已经下线", ResultCodeEnum.FAIL.getCode());
        }
        goods.setStatus(0);
        updateById(goods);
        //生成操作表
        operationService.createOperation(goods, "下线成功", 5);
        return true;
    }

    @Override
    @Transactional
    public void goodsBathesOnline(ApproveDto approveDto) {
        for (Long id : approveDto.getIds()) {
            goodsOnline(id);
        }
    }

    @Override
    public boolean goodsOnline(Long id) {
        Goods goods = getById(id);
        if (goods == null) {
            throw new ShopManageException("无此商品", ResultCodeEnum.FAIL.getCode());
        }
        LoginUser loginUser = SecurityContextHolder.getLoginUser();
        if (!Objects.equals(goods.getManageUserId(), loginUser.getId()) && !Objects.equals(loginUser.getRole(), RoleConstant.ADMIN)) {
            throw new ShopManageException("商品" + id + ":" + "无权限发起上线", ResultCodeEnum.FAIL.getCode());
        }
        if (goods.getStatus() == 1) {
            throw new ShopManageException("商品" + id + ":" + "已经上线", ResultCodeEnum.FAIL.getCode());
        }
        if (goods.getApprovalStatus() != 2) {
            throw new ShopManageException("商品" + id + ":" + "未通过审批,无法上线", ResultCodeEnum.FAIL.getCode());
        }
        //未到上线时间无法上线
        if (!new DateTime(goods.getOnTime()).isBeforeNow()) {
            throw new ShopManageException("商品" + id + ":" + "未到上线时间，无法上线", ResultCodeEnum.FAIL.getCode());
        }
        //下线时间之后无法上线
        if (goods.getDownTime() !=null && new DateTime(goods.getDownTime()).isBeforeNow()) {
            throw new ShopManageException("商品" + id + ":" + "上线时间已过，无法上线", ResultCodeEnum.FAIL.getCode());
        }
        goods.setStatus(1);
        updateById(goods);
        //生成操作表
        operationService.createOperation(goods, "上线成功", 4);
        return true;
    }

    //商品详情
    @Override
    public GoodsVo getGoodsDetailById(Long goodsId, Long userId) {
        Goods goods = goodsMapper.selectById(goodsId);
        if (goods == null) {
            throw new ShopManageException("查无此商品", ResultCodeEnum.FAIL.getCode());
        }
        Long createUserId = goods.getCreateUserId();
        GoodsProxy goodsProxy = goodsProxyService.getGoodsProxy(goodsId, userId);
        if (!Objects.equals(createUserId, userId) && goodsProxy == null) {
            throw new ShopManageException("您没有权限", ResultCodeEnum.FAIL.getCode());
        }
        GoodsVo goodsVo = new GoodsVo();
        try {
            BeanUtils.copyProperties(goods,goodsVo );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return goodsVo;
    }

    //商品预览
    @Override
    public PreviewVo getGoodsPreviewById(Long goodsId,Long userId) {
        Goods goods = goodsMapper.selectById(goodsId);
        if (goods == null) {
            throw new ShopManageException("查无此商品", ResultCodeEnum.FAIL.getCode());
        }
        Long createUserId = goods.getCreateUserId();
        GoodsProxy goodsProxy = goodsProxyService.getGoodsProxy(goodsId, userId);
        if (!Objects.equals(createUserId, userId) && goodsProxy == null) {
            throw new ShopManageException("您没有权限", ResultCodeEnum.FAIL.getCode());
        }
        PreviewVo previewVo = new PreviewVo();
        try {
            BeanUtils.copyProperties(goods, previewVo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return previewVo;
    }

    //商品编辑
    @Override
    public Goods goodsEditingById(Long goodsId,Long userId) {
        Goods goods = goodsMapper.selectById(goodsId);
        if (goods == null) {
            throw new ShopManageException("查无此商品", ResultCodeEnum.FAIL.getCode());
        }
        Long createUserId = goods.getCreateUserId();
        GoodsProxy goodsProxy = goodsProxyService.getGoodsProxy(goodsId, userId);
        if (!Objects.equals(createUserId, userId) && goodsProxy == null) {
            throw new ShopManageException("您没有权限", ResultCodeEnum.FAIL.getCode());
        }
        return goods;
    }

    //转交管理人
    @Override
    public void goodsTransferManagement(Long goodsId, String userName) {
        if(goodsId == null){
            throw new ShopManageException("没有选择商品", ResultCodeEnum.FAIL.getCode());
        }
        Goods goods = goodsMapper.selectById(goodsId);
        if (goods == null) {
            throw new ShopManageException("没有找到该商品", ResultCodeEnum.FAIL.getCode());
        }
        if (userName == null) {
            throw new ShopManageException("没有选择新的管理人", ResultCodeEnum.FAIL.getCode());
        }
        Long userId = userFeignService.selectIdByName(userName);
        if (userId == null) {
            throw new ShopManageException("没有找到转交的管理人", ResultCodeEnum.FAIL.getCode());
        }
        goodsMapper.goodsTransferManagement(goodsId,userId);
    }

    @Override
    public boolean goodsApprove(ApproveDto approveDto) {
        GoodsDraft goodsDraft = goodsDraftService.getById(approveDto.getId());
        //草稿无法发起审批
        if (goodsDraft != null) {
            throw new ShopManageException("草稿无法发起审批", ResultCodeEnum.FAIL.getCode());
        }
        Goods goods = getById(approveDto.getId());
        if (goods == null) {
            throw new ShopManageException("无此商品", ResultCodeEnum.FAIL.getCode());
        }
        LoginUser loginUser = SecurityContextHolder.getLoginUser();
        if (goods.getManageUserId() != loginUser.getId()) {
            throw new ShopManageException("无权限发起审批", ResultCodeEnum.FAIL.getCode());
        }
        if (goods.getApprovalStatus() == 1) {
            throw new ShopManageException("该商品正在审批", ResultCodeEnum.FAIL.getCode());
        }
        goods.setApprovalStatus(1);
        saveOrUpdate(goods);
        operationService.createOperation(goods, approveDto.getRemark(), 1);
        return true;
    }

    //进行审批
    @Override
    public boolean goodsApproveAfter(ApproveDto approveDto) {
        GoodsDraft goodsDraft = goodsDraftService.getById(approveDto.getId());
        //草稿无法发起审批
        if (goodsDraft != null) {
            throw new ShopManageException("草稿无法进行审批", ResultCodeEnum.FAIL.getCode());
        }
        Goods goods = getById(approveDto.getId());
        if (goods == null) {
            throw new ShopManageException("无此商品", ResultCodeEnum.FAIL.getCode());
        }
        if (goods.getApprovalStatus() != 1) {
            throw new ShopManageException("该商品未发起审批", ResultCodeEnum.FAIL.getCode());
        }
        if (approveDto.getIsPass() == 1) {
            goods.setApprovalStatus(2);
            operationService.createOperation(goods, approveDto.getRemark(), 2);
        } else {
            goods.setApprovalStatus(0);
            operationService.createOperation(goods, approveDto.getRemark(), 3);
        }
        updateById(goods);

        return false;
    }


    //保存不能运送的城市
    private void SaveNonDeliverableCityList(Goods good, List<String> nonDeliverPostalCodeList) {
        if (nonDeliverPostalCodeList != null && nonDeliverPostalCodeList.size() != 0) {
            nonDeliverableCityList = new ArrayList<>();
            for (String noDeliverPostalCode : nonDeliverPostalCodeList) {
                NonDeliverableCity nonDeliverableCity = new NonDeliverableCity();
                nonDeliverableCity.setGoodsId(good.getId());
                nonDeliverableCity.setPostalCode(noDeliverPostalCode);
                nonDeliverableCityList.add(nonDeliverableCity);
            }
            nonDeliverableCityService.saveOrUpdateBatch(nonDeliverableCityList);
        }
    }

    //保存库存城市
    private void saveStorageList(Goods good, List<String> storagePostalCodeList) {
        if (storagePostalCodeList != null && storagePostalCodeList.size() != 0) {
            storagecitiesList = new ArrayList<>();
            for (String storagePostalCode : storagePostalCodeList) {
                Storagecities storagecities = new Storagecities();
                storagecities.setGoodsId(good.getId());
                storagecities.setPostalCode(storagePostalCode);
                storagecitiesList.add(storagecities);
            }
            storagecitiesService.saveOrUpdateBatch(storagecitiesList);
        }
    }

    private void parameterCheck(GoodsDto goodsDto) {
        //进行参数校验
        if (StringUtils.isEmpty(goodsDto.getName()) && goodsDto.getName().length() >= 20)
            throw new ShopManageException("商品名称为空或过长", 204);
        if (StringUtils.isEmpty(goodsDto.getImgUrl())) {
            throw new ShopManageException("图片地址不能为空", 204);
        }
        if (StringUtils.isEmpty(goodsDto.getDescription()) && goodsDto.getName().length() >= 100) {
            throw new ShopManageException("文字描述不能为空", 204);
        }
        if (StringUtils.isEmpty(goodsDto.getType())) {
            throw new ShopManageException("商品类型不能为空", 204);
        }
        //数据库查询是否有该分类进行校验
        if (goodsDto.getCatId() == null) {
            throw new ShopManageException("商品类别不能为空", 204);
        }
        if (StringUtils.isEmpty(goodsDto.getProviderName())) {
            throw new ShopManageException("供应商名称不能为空", 204);
        }
        if (StringUtils.isEmpty(goodsDto.getPhone())) {
            throw new ShopManageException("手机号码不能为空", 204);
        }
        if (StringUtils.isEmpty(goodsDto.getService())) {
            throw new ShopManageException("服务保障不能为空", 204);
        }
        if (goodsDto.getBuyType() != null) {
            if (goodsDto.getBuyType() != 0 && goodsDto.getCashPrice() == null)
                throw new ShopManageException("现金价格不能为空", 204);
        } else {
            throw new ShopManageException("商品价格类型不能为空", 204);
        }
        if (goodsDto.getOnTime() == null) {
            throw new ShopManageException("上线时间不能为空", 204);
        }
    }


    @Override
    public void autoTakeoff(ApproveDto approveDto) {
        //获取所有的商品id
        for(Long id: approveDto.getIds()){
            Goods goods = getById(id);
            if(goods==null)
                continue;
            //判断库存是否为0
            if((goods.getStore() <= 0 && goods.getStatus() == 1)) {
                goods.setStatus(0);
                updateById(goods);
            }
            //判断是否过期
            if(goods.getDownTime()!=null && new DateTime(goods.getDownTime()).isBeforeNow() && goods.getStatus() == 1){
                goods.setStatus(0);
                updateById(goods);
            }

        }
    }




}
